package com.sample.livewallpaperdemo.widget;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.sample.livewallpaperdemo.R;

import org.rajawali3d.renderer.ISurfaceRenderer;
import org.rajawali3d.view.TextureView;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;


public class TimeWeatherTextureView extends TextureView {

    private static final int MSG_UPDATE_TIME_CANVAS = 100;
    private static final int MSG_UPDATE_TEMPERATURE_CANVAS = 101;

    private Context mContext;
    private TimeWeatherRenderer mRenderer;

    private BroadcastReceiver mReceiver;

    private int mNumFirst = -1;
    private int mNumSecond = -1;
    private int mNumThird = -1;
    private int mNumFourth = -1;

    private String mTemperature = "27℃";

    private static HandlerThread sBackgroundThread;
    private static Handler sBackgroundHandler;

    private static void startBackgroundThread() {
        if (sBackgroundThread == null) {
            sBackgroundThread = new HandlerThread("time_weather_widget");
            sBackgroundThread.start();
            sBackgroundHandler = new BackgroundHandler(sBackgroundThread.getLooper());
        }
    }

    public TimeWeatherTextureView(Context context) {
        super(context);
        init(context);
    }

    public TimeWeatherTextureView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public TimeWeatherTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        startBackgroundThread();
    }

    @Override
    public void setSurfaceRenderer(ISurfaceRenderer renderer) throws IllegalStateException {
        super.setSurfaceRenderer(renderer);
        if (renderer instanceof TimeWeatherRenderer) {
            mRenderer = (TimeWeatherRenderer) renderer;
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        updateTime();
        if (mReceiver == null) {
            mReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (intent == null) {
                        return;
                    }
                    String action = intent.getAction();
                    if (Intent.ACTION_TIME_TICK.equals(action)
                            || Intent.ACTION_TIME_CHANGED.equals(action)
                            || Intent.ACTION_TIMEZONE_CHANGED.equals(action)
                            || Intent.ACTION_DATE_CHANGED.equals(action)) {
                        updateTime();
                        // updateDateUI();
                    }
                }
            };
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_TIME_TICK);
            filter.addAction(Intent.ACTION_TIME_CHANGED);
            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
            try {
                mContext.registerReceiver(mReceiver, filter);
            } catch (Error e) {
                // ignore
            }
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mReceiver != null) {
            mContext.unregisterReceiver(mReceiver);
            mReceiver = null;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mRenderer.pickObjectAt(event.getX(), event.getY());
        return super.onTouchEvent(event);
    }

    private static class BackgroundHandler extends Handler {
        BackgroundHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            int what = msg.what;
            switch (what) {
                case MSG_UPDATE_TIME_CANVAS: {
                    if (msg.obj instanceof TimeWeatherTextureView) {
                        TimeWeatherTextureView textureView = (TimeWeatherTextureView) msg.obj;
                        textureView.updateTimeBitmap();
                    }
                    break;
                }
                case MSG_UPDATE_TEMPERATURE_CANVAS: {
                    if (msg.obj instanceof TimeWeatherTextureView) {
                        TimeWeatherTextureView textureView = (TimeWeatherTextureView) msg.obj;
                        textureView.updateTemperatureBitmap();
                    }
                    break;
                }
                default:
                    break;
            }
        }
    }

    private void updateTime() {
        Calendar c = Calendar.getInstance();
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);

        if (!android.text.format.DateFormat.is24HourFormat(getContext())) {
            if (hour == 0) {
                hour += 12;
            } else {
                hour = hour > 12 ? hour - 12 : hour;
            }
        }
        int first = hour / 10;
        int second = hour % 10;
        int third = minute / 10;
        int fourth = minute % 10;

        if (first != mNumFirst || second != mNumSecond || third != mNumThird || fourth != mNumFourth) {
            mNumFirst = first;
            mNumSecond = second;
            mNumThird = third;
            mNumFourth = fourth;
            Message msg = sBackgroundHandler.obtainMessage(MSG_UPDATE_TIME_CANVAS, this);
            msg.sendToTarget();
            msg = sBackgroundHandler.obtainMessage(MSG_UPDATE_TEMPERATURE_CANVAS, this);
            msg.sendToTarget();
        }
    }

    /**
     * 耗时操作需要放到后台线程
     */
    private void updateTimeBitmap() {
        Canvas canvas = mRenderer.getTimeCanvas();
        if (canvas != null) {
            //
            // -- Clear the canvas, transparent
            //
            canvas.drawColor(0, PorterDuff.Mode.CLEAR);

            //
            // -- Draw the time on the canvas
            //
            int xPosition = 0;
            // first
            Bitmap bmp = TimeWeatherUtil.getBitmapByNumber(mContext, mNumFirst);
            RectF dest = new RectF(xPosition, 0, bmp.getWidth(), bmp.getHeight());
            canvas.drawBitmap(bmp, null, dest, null);
            xPosition += bmp.getWidth();
            // second
            bmp = TimeWeatherUtil.getBitmapByNumber(mContext, mNumSecond);
            dest = new RectF(xPosition, 0, bmp.getWidth() + xPosition, bmp.getHeight());
            canvas.drawBitmap(bmp, null, dest, null);
            xPosition += bmp.getWidth();
            // :
            int linkRes = R.drawable.time_num_link;
            if (mNumSecond == 1) {
                if (mNumThird == 1) {
                    linkRes = R.drawable.time_num_link;
                } else {
                    linkRes = R.drawable.time_num_link_left;
                }
            } else if (mNumThird == 1) {
                linkRes = R.drawable.time_num_link_right;
            } else {
                linkRes = R.drawable.time_num_link;
            }
            bmp = TimeWeatherUtil.getBitmapByResId(mContext, linkRes);
            dest = new RectF(xPosition, 0, bmp.getWidth() + xPosition, bmp.getHeight());
            canvas.drawBitmap(bmp, null, dest, null);
            xPosition += bmp.getWidth();
            // third
            bmp = TimeWeatherUtil.getBitmapByNumber(mContext, mNumThird);
            dest = new RectF(xPosition, 0, bmp.getWidth() + xPosition, bmp.getHeight());
            canvas.drawBitmap(bmp, null, dest, null);
            xPosition += bmp.getWidth();
            // forth
            bmp = TimeWeatherUtil.getBitmapByNumber(mContext, mNumFourth);
            dest = new RectF(xPosition, 0, bmp.getWidth() + xPosition, bmp.getHeight());
            canvas.drawBitmap(bmp, null, dest, null);

            // -- apply
            mRenderer.updateTimeCanvas();
            requestRenderUpdate();
        }
    }

    /**
     * 耗时操作需要放到后台线程
     */
    private Paint mTemperaturePaint;
    private void updateTemperatureBitmap() {
        if (TextUtils.isEmpty(mTemperature)) {
            return;
        }
        if (mTemperaturePaint == null) {
            mTemperaturePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mTemperaturePaint.setTextSize(60);
            mTemperaturePaint.setColor(Color.RED);
            mTemperaturePaint.setTextAlign(Paint.Align.CENTER);
            Typeface typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL);
            mTemperaturePaint.setTypeface(typeface);
        }
        Canvas canvas = mRenderer.getTemperatureCanvas();
        if (canvas != null) {
            //
            // -- Clear the canvas, transparent
            //
            canvas.drawColor(0, PorterDuff.Mode.CLEAR);

            //
            // -- Draw the temperature on the canvas
            //
            Rect bounds = new Rect();
            mTemperaturePaint.getTextBounds(mTemperature, 0, mTemperature.length(), bounds);
            Paint.FontMetricsInt fontMetrics = mTemperaturePaint.getFontMetricsInt();
            float baseline = canvas.getHeight() / 2 + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
            canvas.drawText(mTemperature, canvas.getWidth() / 2, baseline, mTemperaturePaint);

            // -- apply
            mRenderer.updateTemperatureCanvas();
            requestRenderUpdate();
        }
    }
}
